﻿using System;
using System.Collections.Generic;
using System.Text;

namespace RouterControl.LocalDb
{
    partial class LocalDbConnector
    {
        public struct TrafficInfo
        {
            public DateTime TimeStamp;
            public int UpBytesPerSecond;
            public int DownBytesPerSecond;

            public static readonly TrafficInfo Empty = new TrafficInfo()
            {
                TimeStamp = DateTime.MinValue,
                UpBytesPerSecond = 0,
                DownBytesPerSecond = 0
            };
        }

        public void AddTrafficInfo(DeviceInfo device, TrafficInfo traffic)
        {
            if (device.Id <= 0)
                throw new ArgumentException("invalid device", "device");

            try
            {
	            // query data
	            var cmd = _db.CreateCommand();
	
	            cmd.CommandText = "insert into Traffic (DeviceId,TimeStamp,UpBytesPS,DownBytesPS) values (@id,@t,@up,@dn)";
	            cmd.Parameters.AddWithValue("@id", device.Id);
	            cmd.Parameters.AddWithValue("@t", traffic.TimeStamp);
	            cmd.Parameters.AddWithValue("@up", traffic.UpBytesPerSecond);
	            cmd.Parameters.AddWithValue("@dn", traffic.DownBytesPerSecond);
	
	            // insert
	            cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                _log.Error("Local DB failed: AddTrafficInfo()", ex);

                throw;
            }
        }

        public IList<TrafficInfo> GetTrafficInfo(DeviceInfo device)
        {
            return GetTrafficInfo(device, -1);
        }

        /// <summary>
        /// retrieves the traffic data.
        /// 
        /// newest entries last (FIFO).
        /// 
        /// the amount of entries returned is limited by 'entryCount'.
        /// a value of -1 returns ALL entries.
        /// </summary>
        public IList<TrafficInfo> GetTrafficInfo(DeviceInfo device, int entryCount)
        {
            if (device.Id <= 0)
                throw new ArgumentException("invalid device", "device");

            try
            {
	            // query data
	            var cmd = _db.CreateCommand();
	
	            if (entryCount < 0)
	            {
	                cmd.CommandText = "select TimeStamp,UpBytesPS,DownBytesPS from Traffic where DeviceId=@id order by TimeStamp desc";
	                cmd.Parameters.AddWithValue("@id", device.Id);
	            }
	            else
	            {
	                cmd.CommandText = "select TimeStamp,UpBytesPS,DownBytesPS from Traffic where DeviceId=@id order by TimeStamp desc limit " + entryCount;
	                cmd.Parameters.AddWithValue("@id", device.Id);
	            }
	
	            // read data
	            using (var r = cmd.ExecuteReader())
	            {
	                var ret = new List<TrafficInfo>();
	
	                while (r.Read())
	                {
	                    ret.Add(new TrafficInfo()
	                    {
	                        TimeStamp = r.GetDateTime(0),
	                        UpBytesPerSecond = r.GetInt32(1),
	                        DownBytesPerSecond = r.GetInt32(2)
	                    });
	                }

                    // FILO -> FIFO
                    ret.Reverse();
	
	                return ret.AsReadOnly();
	            }
            }
            catch (Exception ex)
            {
                _log.Error("Local DB failed: GetTrafficInfo()", ex);

                throw;
            }
        }

        public IList<TrafficInfo> GetTrafficInfoSince(DeviceInfo device, DateTime since)
        {
            return GetTrafficInfoSince(device, since, -1);
        }

        /// <summary>
        /// retrieves the traffic data.
        /// 
        /// newest entries last (FIFO).
        /// 
        /// the amount of entries returned is limited by 'entryCount'.
        /// a value of -1 returns ALL entries.
        /// </summary>
        public IList<TrafficInfo> GetTrafficInfoSince(DeviceInfo device, DateTime since, int entryCount)
        {
            if (device.Id <= 0)
                throw new ArgumentException("invalid device", "device");

            try
            {
	            // query data
	            var cmd = _db.CreateCommand();
	
	            if (entryCount < 0)
	            {
	                cmd.CommandText = "select TimeStamp,UpBytesPS,DownBytesPS from Traffic where DeviceId=@id and TimeStamp>@since order by TimeStamp desc";
	                cmd.Parameters.AddWithValue("@id", device.Id);
	                cmd.Parameters.AddWithValue("@since", since);
	            }
	            else
	            {
	                cmd.CommandText = "select TimeStamp,UpBytesPS,DownBytesPS from Traffic where DeviceId=@id and TimeStamp>@since order by TimeStamp desc limit " + entryCount;
	                cmd.Parameters.AddWithValue("@id", device.Id);
	                cmd.Parameters.AddWithValue("@since", since);
	            }
	
	            // read data
	            using (var r = cmd.ExecuteReader())
	            {
	                var ret = new List<TrafficInfo>();
	
	                while (r.Read())
	                {
	                    ret.Add(new TrafficInfo()
	                    {
	                        TimeStamp = r.GetDateTime(0),
	                        UpBytesPerSecond = r.GetInt32(1),
	                        DownBytesPerSecond = r.GetInt32(2)
	                    });
	                }

                    // FILO -> FIFO
                    ret.Reverse();
	
	                return ret.AsReadOnly();
	            }
            }
            catch (Exception ex)
            {
                _log.Error("Local DB failed: GetTrafficInfoSince()", ex);

                throw;
            }
        }
    }
}
